package com.socket.client.point;

import cn.hutool.extra.spring.SpringUtil;
import com.socket.client.handler.message.MessageParser;
import com.socket.client.manager.AuthnManager;
import com.socket.client.manager.UserManager;
import com.socket.client.model.chat.ChatUser;
import com.socket.client.model.chat.UserExt;
import com.socket.client.util.NettyUtil;
import com.socket.core.model.command.enmus.Command;
import io.netty.handler.codec.http.HttpHeaders;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.yeauty.annotation.*;
import org.yeauty.pojo.Session;

import java.util.Optional;

/**
 * Socket端点处理类
 */
@Slf4j
@Component
@ServerEndpoint(path = "${server.path}", port = "${server.port}")
public class SocketEndpoint {
    private final MessageParser messageParser;
    private final AuthnManager authnManager;
    private final UserManager userManager;
    private ChatUser self;

    public SocketEndpoint() {
        this.messageParser = SpringUtil.getBean(MessageParser.class);
        this.authnManager = SpringUtil.getBean(AuthnManager.class);
        this.userManager = SpringUtil.getBean(UserManager.class);
    }

    @BeforeHandshake
    public void handshake(Session session, HttpHeaders headers) {
        UserExt ext = NettyUtil.getExtUser(headers);
        // token认证
        this.self = userManager.join(session, ext);
        if (self != null) {
            session.setSubprotocols(ext.getToken());
            self.setPlatform(NettyUtil.getPlatform(headers));
        }
    }

    @OnOpen
    public void onOpen(Session session) {
        Optional.ofNullable(self).ifPresent(user -> {
            log.debug("===> 用户加入聊天室：{}", user.getGuid());
            // 向其他人发送加入通知
            userManager.sendAll(Command.JOIN, user);
            // 检查禁言
            authnManager.checkMute(user);
        });
    }

    @OnClose
    public void onClose(Session session) {
        Optional.ofNullable(self).ifPresent(user -> {
            log.debug("<=== 用户退出聊天室：{}", user.getGuid());
            userManager.exit(user, session);
        });
    }

    @OnError
    public void onError(Throwable e) {
        e.printStackTrace();
    }

    @OnMessage
    public void onMessage(String json) {
        self.decrypt(json).ifPresent(messageParser::parse);
    }
}
